(function() {
    var AlterTable, BooleanValue, CreateTable, Delete, DropTable, Field, FieldDef, FunctionCastValue, FunctionValue, Group, Having, Insert, Join, Limit, LiteralValue, NumberValue, Op, Order, OrderArgument, QueryPlan, Select, Star, StringValue, SubQuery, SubSelect, Table, Union, Update, Where, indent;

    indent = function(str) {
        var line;
        return ((function() {
            var _i, _len, _ref, _results;
            _ref = str.split("\n");
            _results = [];
            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                line = _ref[_i];
                _results.push("  " + line);
            }
            return _results;
        })()).join("\n");
    };

    exports.QueryPlan = QueryPlan = (function() {
        function QueryPlan(query) {
            this.query = query;
        }

        return QueryPlan;

    })();

    exports.Select = Select = (function() {
        function Select(fields, source, distinct, joins, unions) {
            this.fields = fields;
            this.source = source;
            this.distinct = distinct != null ? distinct : false;
            this.joins = joins != null ? joins : [];
            this.unions = unions != null ? unions : [];
            this.order = null;
            this.group = null;
            this.where = null;
            this.limit = null;
        }

        Select.prototype.toString = function() {
            var join, ret, union, _i, _j, _len, _len1, _ref, _ref1;
            ret = ["SELECT " + (this.fields.join(', '))];
            ret.push(indent("FROM " + this.source));
            _ref = this.joins;
            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                join = _ref[_i];
                ret.push(indent(join.toString()));
            }
            if (this.where) {
                ret.push(indent(this.where.toString()));
            }
            if (this.group) {
                ret.push(indent(this.group.toString()));
            }
            if (this.order) {
                ret.push(indent(this.order.toString()));
            }
            if (this.limit) {
                ret.push(indent(this.limit.toString()));
            }
            _ref1 = this.unions;
            for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
                union = _ref1[_j];
                ret.push(union.toString());
            }
            return ret.join("\n");
        };

        return Select;

    })();

    exports.Insert = Insert = (function() {
        function Insert(target, insertExpression, fields) {
            this.target = target;
            this.insertExpression = insertExpression;
            this.fields = fields;
        }

        Insert.prototype.toString = function() {
            var ret;
            return ret = "";
        };

        return Insert;

    })();

    exports.Delete = Delete = (function() {
        function Delete(target, deleteCondition) {
            this.target = target;
            this.deleteCondition = deleteCondition;
        }

        Delete.prototype.toString = function() {
            var ret;
            return ret = "";
        };

        return Delete;

    })();

    exports.Update = Update = (function() {
        function Update(target, assignList, updateCondition) {
            this.target = target;
            this.assignList = assignList;
            this.updateCondition = updateCondition;
        }

        Update.prototype.toString = function() {
            var ret;
            return ret = "";
        };

        return Update;

    })();

    exports.CreateTable = CreateTable = (function() {
        function CreateTable(target, fieldDef, ifNotExists) {
            this.target = target;
            this.fieldDef = fieldDef;
            this.ifNotExists = ifNotExists != null ? ifNotExists : false;
        }

        CreateTable.prototype.toString = function() {
            var ret;
            return ret = "";
        };

        return CreateTable;

    })();

    exports.DropTable = DropTable = (function() {
        function DropTable(target, ifExists) {
            this.target = target;
            this.ifExists = ifExists != null ? ifExists : false;
            this.isDrop = true;
        }

        DropTable.prototype.toString = function() {
            var ret;
            return ret = "";
        };

        return DropTable;

    })();

    exports.AlterTable = AlterTable = (function() {
        function AlterTable(target, newName) {
            this.target = target;
            this.newName = newName;
        }

        AlterTable.prototype.toString = function() {
            var ret;
            return ret = "";
        };

        return AlterTable;

    })();

    exports.SubSelect = SubSelect = (function() {
        function SubSelect(select, name) {
            this.select = select;
            this.name = name != null ? name : null;
        }

        SubSelect.prototype.toString = function() {
            var ret;
            ret = [];
            ret.push('(');
            ret.push(indent(this.select.toString()));
            ret.push(this.name ? ") " + (this.name.toString()) : ")");
            return ret.join("\n");
        };

        return SubSelect;

    })();

    exports.SubQuery = SubQuery = (function() {
        function SubQuery(select) {
            this.select = select;
            this.fields = this.select.fields;
            this.source = this.select.source;
            this.distinct = this.select.distinct;
            this.joins = this.select.joins;
            this.unions = this.select.unions;
            this.group = this.select.group;
            this.where = this.select.where;
            delete this.select;
        }

        SubQuery.prototype.toString = function() {
            var join, ret, union, _i, _j, _len, _len1, _ref, _ref1;
            ret = ["SELECT " + (this.fields.join(', '))];
            ret.push(indent("FROM " + this.source));
            _ref = this.joins;
            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                join = _ref[_i];
                ret.push(indent(join.toString()));
            }
            if (this.where) {
                ret.push(indent(this.where.toString()));
            }
            if (this.group) {
                ret.push(indent(this.group.toString()));
            }
            _ref1 = this.unions;
            for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
                union = _ref1[_j];
                ret.push(union.toString());
            }
            return ret.join("\n");
        };

        return SubQuery;

    })();

    exports.Join = Join = (function() {
        function Join(right, conditions, side, mode) {
            this.right = right;
            this.conditions = conditions != null ? conditions : null;
            this.side = side != null ? side : null;
            this.mode = mode != null ? mode : 'INNER';
        }

        Join.prototype.toString = function() {
            var ret;
            ret = '';
            if (this.side != null) {
                ret += "" + this.side + " ";
            }
            if (this.mode != null) {
                ret += "" + this.mode + " ";
            }
            return ret + ("JOIN " + this.right + "\n") + indent("ON " + this.conditions);
        };

        return Join;

    })();

    exports.Union = Union = (function() {
        function Union(query, all) {
            this.query = query;
            this.all = all != null ? all : false;
        }

        Union.prototype.toString = function() {
            var all;
            all = this.all ? ' ALL' : '';
            return "UNION" + all + "\n" + (this.query.toString());
        };

        return Union;

    })();

    exports.LiteralValue = LiteralValue = (function() {
        function LiteralValue(value, value2) {
            this.value = value;
            this.value2 = value2 != null ? value2 : null;
            if (this.value2) {
                this.nested = true;
                this.values = this.value.values;
                this.values.push(value2);
            }
            else {
                this.nested = false;
                this.values = [this.value];
            }
        }

        LiteralValue.prototype.toString = function() {
            return "" + (this.values.join('.'));
        };

        return LiteralValue;

    })();

    exports.StringValue = StringValue = (function() {
        function StringValue(value, quoteType) {
            this.value = value;
            this.quoteType = quoteType != null ? quoteType : "''";
        }

        StringValue.prototype.toString = function() {
            return "" + this.quoteType + this.value + this.quoteType;
        };

        return StringValue;

    })();

    exports.NumberValue = NumberValue = (function() {
        function NumberValue(value, sign) {
            this.value = value;
            this.sign = sign != null ? sign : '+';
            this.value = (function() {
                switch (sign) {
                    case '-':
                        return Number(value) * -1;
                    default:
                        return Number(value);
                }
            })();
        }

        NumberValue.prototype.toString = function() {
            if (this.value < 0) {
                return '-' + this.value.toString();
            }
            else {
                return this.value.toString();
            }
        };

        return NumberValue;

    })();

    exports.BooleanValue = BooleanValue = (function() {
        function BooleanValue(value) {
            this.value = (function() {
                switch (value.toLowerCase()) {
                    case 'true':
                        return true;
                    case 'false':
                        return false;
                    default:
                        return null;
                }
            })();
        }

        BooleanValue.prototype.toString = function() {
            if (this.value != null) {
                return this.value.toString().toUpperCase();
            }
            else {
                return 'NULL';
            }
        };

        return BooleanValue;

    })();

    exports.FunctionValue = FunctionValue = (function() {
        function FunctionValue(name, _arguments, udf, isDistinct) {
            var _name;
            this.name = name;
            this["arguments"] = _arguments != null ? _arguments : [];
            this.udf = udf != null ? udf : false;
            _name = name.toLowerCase();
            if (!(_name === "count" || _name === "avg") && isDistinct === true) {
                throw new Error("Parser Error -- only count function should have distinct.");
            }
            if (_name === "count" || _name === "avg") {
                this["arguments"][1] = isDistinct;
            }
        }

        FunctionValue.prototype.toString = function() {
            return "" + this.name + "(" + (this["arguments"].join(', ')) + ")";
        };

        return FunctionValue;

    })();

    exports.FunctionCastValue = FunctionCastValue = (function() {
        function FunctionCastValue(name, expression, toType) {
            this.name = name;
            this.expression = expression;
            this.toType = toType;
        }

        FunctionCastValue.prototype.toString = function() {
            return "" + this.name + "(" + this.expression + " AS " + this.toType + ")";
        };

        return FunctionCastValue;

    })();

    exports.Order = Order = (function() {
        function Order(orderings) {
            this.orderings = orderings;
        }

        Order.prototype.toString = function() {
            return "ORDER BY " + (this.orderings.join(', '));
        };

        return Order;

    })();

    exports.OrderArgument = OrderArgument = (function() {
        function OrderArgument(value, direction, collation) {
            this.value = value;
            this.direction = direction != null ? direction : 'ASC';
            this.collation = collation != null ? collation : "";
        }

        OrderArgument.prototype.toString = function() {
            return "" + this.value + " " + this.collation + " " + this.direction;
        };

        return OrderArgument;

    })();

    exports.Limit = Limit = (function() {
        function Limit(pageNo, numRows) {
            this.pageNo = pageNo != null ? pageNo : null;
            this.numRows = numRows;
        }

        Limit.prototype.toString = function() {
            if (this.pageNo) {
                return "LIMIT " + this.numRows;
            }
            else {
                return "LIMIT " + this.pageNo + ", " + this.numRows;
            }
        };

        return Limit;

    })();

    exports.Table = Table = (function() {
        function Table(name, win, winFn, winArg) {
            this.name = name;
            this.win = win != null ? win : null;
            this.winFn = winFn != null ? winFn : null;
            this.winArg = winArg != null ? winArg : null;
        }

        Table.prototype.toString = function() {
            if (this.win) {
                return "" + this.name + "." + this.win + ":" + this.winFn + "(" + this.winArg + ")";
            }
            else {
                return this.name.toString();
            }
        };

        return Table;

    })();

    exports.Group = Group = (function() {
        function Group(fields) {
            this.fields = fields;
            this.having = null;
        }

        Group.prototype.toString = function() {
            var ret;
            ret = ["GROUP BY " + (this.fields.join(', '))];
            if (this.having) {
                ret.push(this.having.toString());
            }
            return ret.join("\n");
        };

        return Group;

    })();

    exports.Where = Where = (function() {
        function Where(conditions) {
            this.conditions = conditions;
        }

        Where.prototype.toString = function() {
            return "WHERE " + this.conditions;
        };

        return Where;

    })();

    exports.Having = Having = (function() {
        function Having(conditions) {
            this.conditions = conditions;
        }

        Having.prototype.toString = function() {
            return "HAVING " + this.conditions;
        };

        return Having;

    })();

    exports.Op = Op = (function() {
        function Op(operation, left, right) {
            this.operation = operation;
            this.left = left;
            this.right = right;
        }

        Op.prototype.toString = function() {
            return "(" + this.left + " " + this.operation + " " + this.right + ")";
        };

        return Op;

    })();

    exports.Field = Field = (function() {
        function Field(field, name) {
            this.field = field;
            this.name = name != null ? name : null;
        }

        Field.prototype.toString = function() {
            if (this.name) {
                return "" + this.field + " AS " + this.name;
            }
            else {
                return this.field.toString();
            }
        };

        return Field;

    })();

    exports.FieldDef = FieldDef = (function() {
        function FieldDef(field, type, isNullable, isPK, isAutoInc) {
            this.field = field;
            this.type = type;
            this.isNullable = isNullable;
            this.isPK = isPK;
            this.isAutoInc = isAutoInc;
        }

        FieldDef.prototype.toString = function() {
            return "";
        };

        return FieldDef;

    })();

    exports.Star = Star = (function() {
        function Star(literal) {
            this.literal = literal;
            this.star = true;
        }

        Star.prototype.toString = function() {
            return "" + this.literal + "*";
        };

        return Star;

    })();

}).call(this);